using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using Newtonsoft.Json;

public class SiliconData
{
    public string TmpFile { get; private set; }
    public string AppendFile { get; set; }
    string logPath = HttpContext.Current.Server.MapPath("~/debug_file1.txt");

    public SiliconData(string deviceId)
    {
        LogToFile(logPath, "entered, public SiliconData(string deviceId)");

        // Validate deviceId
        if (string.IsNullOrWhiteSpace(deviceId) || !int.TryParse(deviceId, out _))
        {
            LogToFile(logPath, "Error: Invalid or missing deviceId");
            throw new ArgumentException("Invalid deviceId. Must be a non-empty integer.");
        }

        // Generate unique temp file path (does NOT create the file yet)
        TmpFile = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N") + ".tmp");

        // Sanitize deviceId to remove illegal filename characters
        string safeDeviceId = Path.GetInvalidFileNameChars()
            .Aggregate(deviceId, (current, c) => current.Replace(c.ToString(), ""));

        // Build append file path
        AppendFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, safeDeviceId + "_tmp.dat");

        LogToFile(logPath, $"TmpFile path set to: {TmpFile}");
        LogToFile(logPath, $"AppendFile path set to: {AppendFile}");
        LogToFile(logPath, "exit, public SiliconData(string deviceId)");
    }

    void LogToFile(string path, string content)
    {
        try
        {
            File.AppendAllText(path, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " - " + content + Environment.NewLine);
        }
        catch
        {
            // Optional: Suppress logging errors or handle accordingly
        }
    }

    public void Append(Stream input, int blkNo)
    {
        using (FileStream fs = new FileStream(AppendFile, blkNo == 1 ? FileMode.Create : FileMode.Append))
        {
            input.CopyTo(fs);
        }
    }

    public Dictionary<string, object> Get(Stream input)
    {
        using (FileStream fs = new FileStream(TmpFile, FileMode.Create))
        {
            input.CopyTo(fs);
        }

        byte[] tempData = File.ReadAllBytes(TmpFile);
        byte[] appendData = File.Exists(AppendFile) ? File.ReadAllBytes(AppendFile) : new byte[0];

        byte[] contents = new byte[appendData.Length + tempData.Length];
        Buffer.BlockCopy(appendData, 0, contents, 0, appendData.Length);
        Buffer.BlockCopy(tempData, 0, contents, appendData.Length, tempData.Length);

        Dictionary<string, object> result = new Dictionary<string, object>();
        int i = 0, j = -1;
        while (i < contents.Length)
        {
            int len = BitConverter.ToInt32(contents, i);
            i += 4;
            byte[] block = new byte[len];
            Buffer.BlockCopy(contents, i, block, 0, len);
            i += len;

            j++;
            if (j == 0)
            {
                string json = Encoding.UTF8.GetString(block).TrimEnd('\0');
                result = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
            }
            else
            {
                result["BIN_" + j] = BitConverter.ToString(block).Replace("-", "").ToLower();
            }
        }

        return result;
    }

    public void Set(string command, string data, HttpResponse response)
    {
        string logPath = HttpContext.Current.Server.MapPath("~/debug_file1.txt");
        LogToFile(logPath, "Entered Set");

        // Default to "OK" if no response_code found
        string responseCode = "OK";
        if (!string.IsNullOrEmpty(command))
        {
            var parts = command.Split('&');
            foreach (var p in parts)
            {
                var kv = p.Split('=');
                if (kv.Length == 2 && kv[0].Trim().ToLower() == "response_code")
                {
                    responseCode = kv[1].Trim();
                    break;
                }
            }
        }

        try
        {
            // Set response headers
            response.Clear();
            response.Buffer = true;
            response.AddHeader("Cache-Control", "private");
            response.AddHeader("Connection", "close");
            response.ContentType = "application/octet-stream";
            response.AddHeader("Expires", "0");
            response.AddHeader("Content-Length", "0");
            response.AddHeader("response_code", responseCode);

            // Do not write anything to the body
            response.Flush();
            response.End();

            LogToFile(logPath, $"Exit Set - Headers sent with response_code: {responseCode}");
        }
        catch (Exception ex)
        {
            LogToFile(logPath, $"Set Error: {ex.Message}");
        }
    }


}
